package com.dhemery.mack.actions.tests;

import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.junit.Before;
import org.junit.Test;

import com.dhemery.mack.actions.ExplorerViewAction;
import com.dhemery.mack.actions.OpenAction;
import com.dhemery.mack.adapters.ImageDescriptorSource;
import com.dhemery.mack.adapters.NodeEditorInput;
import com.dhemery.mack.adapters.tests.FakeConstantImageDescriptorSource;
import com.dhemery.mack.adapters.tests.FakeImageDescriptor;
import com.dhemery.mack.gui.NodeEditor;
import com.dhemery.mack.model.Page;

import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

public class OpenActionTests {
	private ImageDescriptorSource imageDescriptorSource;

	@Before
	public void setup() {
		ImageDescriptor fakeImageDescriptor = new FakeImageDescriptor("fake");
		imageDescriptorSource = new FakeConstantImageDescriptorSource(fakeImageDescriptor);
	}
	
	@Test
	public void startsDisabled() {
		ExplorerViewAction action = new OpenAction(null, mock(TreeViewer.class), null, imageDescriptorSource);

		assertFalse(action.isEnabled());
	}

	@Test
	public void enablesWhenSelectionIsNotEmpty() {
		SelectionChangedEvent event = mock(SelectionChangedEvent.class);
		StructuredSelection selection = mock(StructuredSelection.class);
		Object[] selectedObjects = new Object[] { new Page() };

		stub(selection.toArray()).toReturn(selectedObjects);
		stub(event.getSelection()).toReturn(selection);

		ExplorerViewAction action = new OpenAction(null, mock(TreeViewer.class), null, imageDescriptorSource);

		action.selectionChanged(event);

		assertTrue(action.isEnabled());
	}

	@Test
	public void disablesWhenSelectionIsEmpty() {
		SelectionChangedEvent event = mock(SelectionChangedEvent.class);
		StructuredSelection selection = mock(StructuredSelection.class);
		Object[] selectedObjects = new Object[0];

		stub(selection.toArray()).toReturn(selectedObjects);
		stub(event.getSelection()).toReturn(selection);

		ExplorerViewAction action = new OpenAction(null, mock(TreeViewer.class), null, imageDescriptorSource);

		action.selectionChanged(event);

		assertFalse(action.isEnabled());
	}

	@Test
	public void opensSelectedNodeInEditor() throws PartInitException {
		IWorkbenchPage page = mock(IWorkbenchPage.class);
		TreeViewer viewer = mock(TreeViewer.class);
		IAdapterFactory factory = mock(IAdapterFactory.class);
		StructuredSelection selection = mock(StructuredSelection.class);
		SelectionChangedEvent event = mock(SelectionChangedEvent.class);

		Object[] selectedNodes = new Object[] {
				new Page(),
				};
		NodeEditorInput[] inputs = new NodeEditorInput[] {
				new NodeEditorInput(null, null),
			};

		stub(event.getSelection()).toReturn(selection);
		stub(selection.toArray()).toReturn(selectedNodes);
		stub(factory.getAdapter(same(selectedNodes[0]), eq(IEditorInput.class))).toReturn(inputs[0]);

		ExplorerViewAction action = new OpenAction(page, viewer, factory, imageDescriptorSource);

		action.selectionChanged(event);

		action.run();

		verify(page).openEditor(same(inputs[0]), eq(NodeEditor.ID));
	}

	@Test
	public void opensAllSelectedNodesInEditor() throws PartInitException {
		IWorkbenchPage page = mock(IWorkbenchPage.class);
		TreeViewer viewer = mock(TreeViewer.class);
		IAdapterFactory factory = mock(IAdapterFactory.class);
		StructuredSelection selection = mock(StructuredSelection.class);
		SelectionChangedEvent event = mock(SelectionChangedEvent.class);

		Object[] selectedNodes = new Object[] {
				new Page(),
				new Page(),
				new Page(),
				new Page(),
				new Page(),
				};
		NodeEditorInput[] inputs = new NodeEditorInput[] {
				new NodeEditorInput(null, null),
				new NodeEditorInput(null, null),
				new NodeEditorInput(null, null),
				new NodeEditorInput(null, null),
				new NodeEditorInput(null, null),
			};

		stub(event.getSelection()).toReturn(selection);
		stub(selection.toArray()).toReturn(selectedNodes);
		stub(factory.getAdapter(same(selectedNodes[0]), eq(IEditorInput.class))).toReturn(inputs[0]);
		stub(factory.getAdapter(same(selectedNodes[1]), eq(IEditorInput.class))).toReturn(inputs[1]);
		stub(factory.getAdapter(same(selectedNodes[2]), eq(IEditorInput.class))).toReturn(inputs[2]);
		stub(factory.getAdapter(same(selectedNodes[3]), eq(IEditorInput.class))).toReturn(inputs[3]);
		stub(factory.getAdapter(same(selectedNodes[4]), eq(IEditorInput.class))).toReturn(inputs[4]);

		ExplorerViewAction action = new OpenAction(page, viewer, factory, imageDescriptorSource);

		action.selectionChanged(event);

		action.run();

		verify(page).openEditor(same(inputs[0]), eq(NodeEditor.ID));
		verify(page).openEditor(same(inputs[1]), eq(NodeEditor.ID));
		verify(page).openEditor(same(inputs[2]), eq(NodeEditor.ID));
		verify(page).openEditor(same(inputs[3]), eq(NodeEditor.ID));
		verify(page).openEditor(same(inputs[4]), eq(NodeEditor.ID));
	}
}
